
##================================================##
##                                                ##
##       Computational Social Science             ##
##       Doctoral Seminar (16:194:630)            ##
##       Spring 2026, Rutgers University          ## 
##       Katya Ognyanova, katya@ognyanova.net     ## 
##                                                ##
##================================================##




# A useful resource for APIs available to social scientists:
# https://bookdown.org/paul/apis_for_social_scientists/


# Packages we would need today:
# (remove # and run this if they are not already installed)  


# install.packages("rtweet")           # Get Twitter data
# install.packages("RedditExtractoR")  # Get Reddit data
# install.packages("archiveRetriever") # Get Internet Archive data
# install.packages("igraph")           # Work with networks
# install.packages("wordcloud")        # Create word clouds 
# install.packages("tm")               # Text analysis package


 

# ================ BlueSky API in R ================


# In order to do this, you would have to register an account at https://bsky.app/
# Next, you need to create an app password (different from your account password)
# You can do that at https://bsky.app/settings/app-passwords

# If you run this code on your own machine, you would need to
# install the packages we use here. For BlueSky, that would be:
# install.packages("atrrr")

library(atrrr)

# Authenticate your account. You will be asked for your app password.
auth("research-account.bsky.social") # Replace this with your own account!



#  ------~~~ Search for terms --------  

# Collect posts mentioning a specific search term:

# Get the most recent 500 posts that mention Rutgers
rutgers <- search_post("rutgers", limit=500)
rutgers$text

rutgers$engagement <- rutgers$like_count + 
  rutgers$repost_count + 
  rutgers$quote_count +
  rutgers$reply_count

# Order posts by total engagement, most popular at the top:
post_order <- order(-rutgers$engagement)
rutgers <- rutgers[post_order,]

# Top 10 posts mentioning Rutgers (unfiltered, apologies if any are bad!)
top_ru <- rutgers[1:10, c("author_handle", "author_name", 
                          "text", "engagement" )] 
View(top_ru)


# Let's make a wordcloud with Rutgers-related hashtags

# If you are running this on your own computer, install the necessary package 
# (if you are using RStudio Cloud the package is already installed)
# install.packages("wordcloud")

library(wordcloud)

hashtags <- unlist(rutgers$tags)
hashtags <- hashtags[!is.na(hashtags)]

# Count occurrences
hashtag_counts <- as.data.frame(table(hashtags))
hashtag_counts

# Create word cloud
wordcloud(hashtag_counts$hashtags, hashtag_counts$Freq,
          colors = brewer.pal(8, "Dark2"))

# Clear the word cloud:
dev.off()


#  ------~~~ Account posts --------   

# Collect posts from a specific account: 

# Get the most recent 500 posts from the account WeRateDogs
# https://bsky.app/profile/weratedogs.com/post/3liwvduq23s2j

dogs <- get_skeets_authored_by(actor = "weratedogs.com", limit=500)

most_liked_dog <- dogs[which.max(dogs$like_count), ]
most_liked_txt <- most_liked_dog$text
most_liked_pic <- most_liked_dog$embed_data[[1]]$images[[1]]$fullsize

# Download the picture of the  most liked dog and show it!
library(jpeg)
download.file(most_liked_pic, "dog.jpg", mode = "wb")
dog_pic <- readJPEG("dog.jpg")
grid::grid.raster(dog_pic)
most_liked_txt


# Let's get the sentiment of posts that rate dogs!

# If you are running this on your own computer, install the necessary package 
# (if you are using RStudio Cloud the package is already installed)
# install.packages("syuzhet")

library(syuzhet)

# Sentiment scores  based on scoring words as "positive" or "negative"
sentiment_scores <- get_sentiment(dogs$text, method="bing")
summary(sentiment_scores)

# Post with the most positive sentiment score:
happy <- dogs[which.max(sentiment_scores),]
happy$text
# Open the post URL:
browseURL(convert_at_to_http(happy$uri))

# Post with the least positive sentiment score:
sad <- dogs[which.min(sentiment_scores),]
sad$text
# Open the post URL:
browseURL(convert_at_to_http(sad$uri))


#  ------~~~ Getting emotional! --------  

# Let's get some posts from the NYTimes next:
nyt <- get_skeets_authored_by(actor = "nytimes.com", limit=200)

# How about some getting posts with specific emoptions?
library(syuzhet)

emotions <- get_nrc_sentiment(nyt$text)
head(emotions)

nyt$text[which.max(emotions$joy )]

nyt$text[which.max(emotions$anticipation  )]

nyt$text[which.max(emotions$anger  )]

nyt$text[which.max(emotions$sadness )]

nyt$text[which.max(emotions$disgust )]

nyt$text[which.max(emotions$surprise )]

nyt$text[which.max(emotions$trust )]



#  ------~~~ Followers and followees --------  

# Let's check who follows me on BlueSky!

# Get accounts follwing someone on BlueSky:
followers <- get_followers(actor="ognyanova.bsky.social",limit=2000)

# Get accounts followed by someone on BlueSky:
follows  <- get_follows(actor="ognyanova.bsky.social",limit=2000)

# And here are my true friends!
mutuals <- intersect(followers$actor_handle,
                     follows$actor_handle)
mutuals


# ================  Reddit API in R ================

library("RedditExtractoR")

# Find subreddits about Rutgers:
ru_red <- find_subreddits("rutgers") 

ru_red$subreddit
ru_red$title

# Get threads from a subreddit:
# Reddit offers sorting by "hot", "new", "top", and "rising"
# Period could be hour, day, week, month, year, etc. or all
ru_threads <- find_thread_urls(subreddit="rutgers", 
                               sort_by="top", 
                               period="week")


# Get threads that mention communication:
comm_threads <- find_thread_urls(keywords = "communication",
                                 subreddit="rutgers", 
                                 sort_by="top", 
                                 period="all")
comm_threads$title

# Thread with most comments:
comm_threads$title[which.max(comm_threads$comments)]


# Get the content of a thread, including comments:
comm_content <- get_thread_content(comm_threads$url[1:10])

# Thread data:
threads <- comm_content$threads
names(threads)

# Comment data:
comments <- comm_content$comments
names(comments)

# Get information and content about specific users:
# e.g. we could get threads$author

users <- get_user_content("nasa")

# We get a list with each user as an element.
# For each user, we have three elements:

# Information about the user
nasa_about <- users$nasa$about
nasa_about

# Threads by the user:
nasa_threads <- users$nasa$threads
nasa_threads[1:5,]

# Comments by the user
nasa_comments <- users$nasa$comments
nasa_comments[100,]



# ================  Internet Archive API ================


library("archiveRetriever") 

# Calendar showing when the page was archived 
# within a startDate to endDate period

archive_overview(homepage = "www.nytimes.com", 
                 startDate = "2010-01-01", 
                 endDate = "2010-02-01")

# What are the URLs for a particular page recorded by the archive
# within the selected time period we are interested in?
nyt_urls <- retrieve_urls("www.nytimes.com/section/politics", 
                          startDate = "2020-01-01", 
                          endDate = "2020-01-10")
nyt_urls

# We will discuss web scraping more next week!
# For now, let's just say the following code will get us data
# on the article titles and teaser text from the NYT front page.
nyt <- scrape_urls( Urls = nyt_urls,
                    Paths = c(title = "//article/div/h2//text()", 
                              teaser = "//article/div/p/text()"), 
                    collapse = FALSE, 
                    archiveDate = TRUE)

nyt


# ================ THE END ================






